#pragma once
#include <sys/epoll.h>
#include <unistd.h>
#include "log.hpp"

/*
    epoll模块：负责监听底层文件描述上的对应事件，将就绪事件通知上层
*/
class Epoller
{
private:
    void eventCore(const int &fd, const uint32_t &events, int mode)
    {
        struct epoll_event ev;
        ev.events = events;
        ev.data.fd = fd;
        epoll_ctl(_epoll_fd, mode, fd, &ev);
    }

public:
    Epoller()
    {
        _epoll_fd = epoll_create(128);
        if (_epoll_fd < 0)
        {
            LOG(FATAL, "epoll create failed!\n");
            exit(1);
        }
        LOG(INFO, "epoll create success, epoll fd: %d:\n", _epoll_fd);
    }

    // 添加监听文件描述符和关心事件
    void addEvent(const int &fd, const uint32_t &events)
    {
        eventCore(fd, events, EPOLL_CTL_ADD);
    }

    // 修改监听文件描述的关心事件
    void modEvent(const int &fd, const uint32_t &events)
    {
        eventCore(fd, events, EPOLL_CTL_MOD);
    }

    // 删除文件描述符
    void delEvent(const int &fd)
    {
        epoll_ctl(_epoll_fd, EPOLL_CTL_DEL, fd, nullptr);
    }

    // 获取就绪事件
    int wait(struct epoll_event *ev_arry, int num, int timeout)
    {
        return epoll_wait(_epoll_fd, ev_arry, num, timeout);
    }

    ~Epoller()
    {
        if (_epoll_fd >= 0)
            close(_epoll_fd);
    }

private:
    int _epoll_fd; // epoll模型对应的文件描述符
};